﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Csla;
using System.Collections;
using Csla.Core;
using System.ComponentModel;

namespace Csla
{
    public static class TreeHelper
    {
        /// <summary>
        /// 深度遍历
        /// </summary>
        /// <param name="rootNode"></param>
        /// <param name="action"></param>
        public static void TravelDepthFirst(this ITreeNode rootNode, Action<ITreeNode> action)
        {
            if (rootNode == null) throw new ArgumentNullException("rootNode");
            if (action == null) throw new ArgumentNullException("action");

            Stack<ITreeNode> stack = new Stack<ITreeNode>();

            stack.Push(rootNode);
            while (stack.Count > 0)
            {
                var currentNode = stack.Pop();

                action(currentNode);

                var children = currentNode.ChildrenNodes;
                for (int i = children.Count - 1; i >= 0; i--)
                {
                    var child = children[i];
                    if (child != null)
                    {
                        stack.Push(child);
                    }
                }
            }
        }

        /// <summary>
        /// 广度遍历
        /// </summary>
        /// <param name="rootNode"></param>
        /// <param name="action"></param>
        public static void TravelScopeFirst(this ITreeNode rootNode, Action<ITreeNode> action)
        {
            if (rootNode == null) throw new ArgumentNullException("rootNode");
            if (action == null) throw new ArgumentNullException("action");

            Queue<ITreeNode> queue = new Queue<ITreeNode>();
            queue.Enqueue(rootNode);
            while (queue.Count > 0)
            {
                var node = queue.Dequeue();
                action(node);

                foreach (var childNode in node.ChildrenNodes)
                {
                    if (childNode != null)
                    {
                        queue.Enqueue(childNode);
                    }
                }
            }
        }

        /// <summary>
        /// 得到级联子对象
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public static IList<ITreeNode> GetRecurChildren(this ITreeNode node)
        {
            if (node == null) throw new ArgumentNullException("node");

            var result = new List<ITreeNode>();
            TreeHelper.TravelDepthFirst(node, n =>
            {
                result.Add(n);
            });
            return result;
        }

        /// <summary>
        /// 级联删除当前记录及其所有子，删除过程中注意现删除子在删除父，以便可以正确保存到数据库
        /// </summary>
        /// <param name="node"></param>
        public static void RecurDelete(this ITreeNode node, IBindingList list)
        {
            if (node == null) throw new ArgumentNullException("node");
            if (list == null) throw new ArgumentNullException("list");

            var items = node.GetRecurChildren();
            //先删除细记录再删除主记录
            for (int j = items.Count - 1; j >= 0; j--)
            {
                list.Remove(items[j]);
            }
            list.Remove(node);
        }
        ///// <summary>
        ///// 前一兄弟节点
        ///// 
        ///// 如果有父节点，则计算兄弟节点
        ///// 没有父节点，使用list进行计算前一节点的最上层父节点
        ///// </summary>
        ///// <param name="node"></param>
        ///// <returns></returns>
        //public static ITreeNode PrevNode(this ITreeNode node)
        //{
        //    var parentNode = node.ParentNode;

        //    //如果有父节点，则计算兄弟节点
        //    if (null != parentNode)
        //    {
        //        //前一兄弟节点
        //        var children = parentNode.ChildrenNodes;
        //        int index = children.IndexOf(node) - 1;
        //        return index >= 0 ? children[index] : null;
        //    }
        //    //没有父节点，使用list进行计算前一节点的最上层父节点
        //    else
        //    {
        //        //找到前一节点的位置
        //        IList parent = (node as BusinessBase).Parent as IList;
        //        int index = parent.IndexOf(node) - 1;
        //        if (index < 0)
        //        {
        //            return null;
        //        }

        //        //当list中index处节点的Pid值不为空，则向上寻找
        //        //考虑懒加载关系，这里使用Pid，而不是用ParentNode
        //        while (null != (parent[index] as ITreeNode).Pid)
        //        {
        //            index -= 1;
        //            if (index < 0)
        //            {
        //                return null;
        //            }
        //        }

        //        //返回最上层的父节点
        //        return parent[index] as ITreeNode;
        //    }
        //}
        ///// <summary>
        ///// 后一同级节点
        ///// 
        ///// 如果有父节点，则计算兄弟节点
        ///// 没有父节点，使用list进行计算后一节点的最上层父节点
        ///// </summary>
        ///// <param name="node"></param>
        ///// <returns></returns>
        //public static ITreeNode NextNode(this ITreeNode node)
        //{
        //    var parentNode = node.ParentNode;

        //    //如果有父节点，则计算兄弟节点
        //    if (null != parentNode)
        //    {
        //        var children = parentNode.ChildrenNodes;
        //        int index = children.IndexOf(node) + 1;
        //        return index <= children.Count - 1 ? children[index] : null;
        //    }
        //    //没有父节点，使用list进行计算后一节点的最上层父节点
        //    else
        //    {
        //        //找到后一节点的位置
        //        IList parent = (node as BusinessBase).Parent as IList;
        //        int index = parent.IndexOf(node) + 1;
        //        if (index > parent.Count - 1)
        //        {
        //            return null;
        //        }

        //        //当list中index处节点的Pid值不为空，则向上寻找
        //        //考虑懒加载关系，这里使用Pid，而不是用ParentNode
        //        while (null != (parent[index] as ITreeNode).Pid)
        //        {
        //            index += 1;
        //            if (index > parent.Count - 1)
        //            {
        //                return null;
        //            }
        //        }

        //        //返回最上层的父节点
        //        return parent[index] as ITreeNode;
        //    }
        //}
        ///// <summary>
        ///// 深度排序
        ///// 
        ///// 调用前，先保证已经建立了关系，可调用RebuildRelations方法
        ///// </summary>
        ///// <param name="collection"></param>
        //public static void SortByDepthFirst(IList<ITreeNode> nodesCollection)
        //{
        //    if (nodesCollection == null) throw new ArgumentNullException("nodesCollection");

        //    var rootEntities = FindRootNodes(nodesCollection);

        //    int i = 0;
        //    foreach (ITreeNode root in rootEntities)
        //    {
        //        TreeHelper.TravelDepthFirst(root, n =>
        //        {
        //            nodesCollection[i++] = n;
        //        });
        //    }
        //}
        ///// <summary>
        ///// 深度排序
        ///// 
        ///// 调用前，先保证已经建立了关系，可调用RebuildRelations方法
        ///// </summary>
        ///// <param name="collection"></param>
        //public static void SortByDepthFirst(IList nodesCollection)
        //{
        //    if (nodesCollection == null) throw new ArgumentNullException("nodesCollection");

        //    var rootEntities = FindRootNodes(nodesCollection);

        //    int i = 0;
        //    foreach (ITreeNode root in rootEntities)
        //    {
        //        if (root == null) throw new ArgumentNullException("root");
        //        TreeHelper.TravelDepthFirst(root, n =>
        //        {
        //            nodesCollection[i++] = n;
        //        });
        //    }
        //}
        ///// <summary>
        ///// 广度排序
        ///// 
        ///// 调用前，先保证已经建立了关系，可调用RebuildRelations方法
        ///// </summary>
        ///// <param name="collection"></param>
        //public static void SortByScopeFirst(IList<ITreeNode> nodesCollection)
        //{
        //    if (nodesCollection == null) throw new ArgumentNullException("nodesCollection");

        //    var rootEntities = FindRootNodes(nodesCollection);

        //    int i = 0;
        //    foreach (ITreeNode root in rootEntities)
        //    {
        //        TreeHelper.TravelScopeFirst(root, n =>
        //        {
        //            nodesCollection[i++] = n;
        //        });
        //    }
        //}
        ///// <summary>
        ///// 广度排序
        ///// 
        ///// 调用前，先保证已经建立了关系，可调用RebuildRelations方法
        ///// </summary>
        ///// <param name="collection"></param>
        //public static void SortByScopeFirst(IList nodesCollection)
        //{
        //    if (nodesCollection == null) throw new ArgumentNullException("nodesCollection");

        //    var rootEntities = FindRootNodes(nodesCollection);

        //    int i = 0;
        //    foreach (ITreeNode root in rootEntities)
        //    {
        //        if (root == null) throw new ArgumentNullException("root");
        //        TreeHelper.TravelScopeFirst(root, n =>
        //        {
        //            nodesCollection[i++] = n;
        //        });
        //    }
        //}

        /// <summary>
        /// 建立父子关系
        /// </summary>
        /// <param name="collection"></param>
        public static void RebuildRelations(IEnumerable nodesCollection)
        {
            if (nodesCollection == null) throw new ArgumentNullException("nodesCollection");

            foreach (ITreeNode node in nodesCollection)
            {
                node.ChildrenNodes.Clear();
            }
            foreach (ITreeNode child in nodesCollection)
            {
                if (child.Pid != null)
                {
                    foreach (ITreeNode parent in nodesCollection)
                    {
                        if (parent.Id.Equals(child.Pid))
                        {
                            child.ParentNode = parent;
                            if (parent.ChildrenNodes.Contains(child) == false)
                            {
                                parent.ChildrenNodes.Add(child);
                            }
                            break;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 查找集合中所有的根节点
        /// </summary>
        /// <param name="nodesCollection"></param>
        /// <returns></returns>
        internal static ITreeNode[] FindRootNodes(IEnumerable nodesCollection)
        {
            return nodesCollection.Cast<ITreeNode>().Where(n => n.Pid == null).ToArray();
        }

        /// <summary>
        /// 统计一个这个树的所有节点个数
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        internal static int CountTreeNode(this ITreeNode node)
        {
            int treeNodeCount = 0;
            node.TravelScopeFirst(n =>
            {
                treeNodeCount++;
            });
            return treeNodeCount;
        }
    }
}